"""定义成员模型类的文件."""
from datetime import datetime

from fastapi import Body
from pydantic import BaseModel, ConfigDict, EmailStr, field_validator, model_validator

from lib.member import set_zip_code
from lib.pbkdf2 import create_hash

from api.v1.service.member import MemberImageServiceAPI as ImageService
from api.v1.models.response import MessageResponse

class CreateMember(BaseModel):
    """会员信息模型"""
    # 允许其他字段
    model_config = ConfigDict(extra='allow')

    mb_id: str = Body(..., min_length=3, max_length=20, pattern=r"^[a-zA-Z0-9_]+$",
                      title="Idie", description="3~20椅子的英文, 编号, _仅可用.")
    mb_password: str = Body(..., title="密码", min_length=4, max_length=20)
    mb_password_re: str = Body(..., title="检查您的密码", min_length=4, max_length=20)
    mb_nick: str = Body(..., title="昵称")
    mb_name: str = Body(..., title="姓名")
    mb_sex: str = Body("", pattern=r"^[mf]?$", title="性别")
    mb_email: EmailStr = Body(..., title="电子邮件", description="请输入您的电子邮件格式.")
    mb_homepage: str = Body("", title="主页")
    mb_zip: str = Body("", title="邮政号码")
    mb_addr_jibeon: str = Body("", title="地址")
    mb_addr1: str = Body("", title="基本地址")
    mb_addr2: str = Body("", title="地址的其余部分")
    mb_addr3: str = Body("", title="其他地址")
    mb_tel: str = Body("", title="电话号码")
    mb_hp: str = Body("", title="移动电话号码")
    mb_signature: str = Body("", title="签名")
    mb_profile: str = Body("", title="自我介绍")
    mb_recommend: str = Body("", title="推荐ID")

    mb_mailling: int = Body(0, title="不管你是否收到邮件")
    mb_sms: int = Body(0, title="SMS 是否接收")
    mb_open: int = Body(0, title="	是否公开会员信息")

    mb_1: str = Body("", title="额外字段1")
    mb_2: str = Body("", title="额外字段2")
    mb_3: str = Body("", title="额外字段3")
    mb_4: str = Body("", title="额外字段4")
    mb_5: str = Body("", title="额外字段5")
    mb_6: str = Body("", title="额外字段6")
    mb_7: str = Body("", title="额外字段7")
    mb_8: str = Body("", title="额外字段8")
    mb_9: str = Body("", title="额外字段9")
    mb_10: str = Body("", title="额外字段10")

    @field_validator('mb_zip', mode='after')
    @classmethod
    def divide_zip(cls, v: str) -> str:
        """正面和背面的邮政号码，分别 3被一个地方分开"""
        cls.mb_zip1, cls.mb_zip2 = set_zip_code(v)
        return v

    @model_validator(mode='after')
    def check_passwords_match(self) -> 'CreateMember':
        """检查密码和密码验证是否匹配"""
        pw1 = self.mb_password
        pw2 = self.mb_password_re
        if pw1 is not None and pw2 is not None and pw1 != pw2:
            raise ValueError('密码不匹配.')

        # convert to hash password
        self.mb_password = create_hash(pw1)
        return self

    @model_validator(mode='after')
    def init_fields(self) -> 'CreateMember':
        """CreateMemberModel初始化一个未声明的字段"""
        self.mb_level: int = 1
        self.mb_login_ip: str = ""
        # 删除加入成员不需要的字段
        del self.mb_password_re
        del self.mb_zip

        return self


class UpdateMember(BaseModel):
    """会员信息修正模型"""
    # 允许其他字段
    model_config = ConfigDict(extra='allow')

    mb_password: str = Body(None, title="密码", min_length=4, max_length=20)
    mb_password_re: str = Body(None, title="检查您的密码", min_length=4, max_length=20)
    mb_nick: str = Body(None, title="昵称")
    mb_sex: str = Body(None, pattern=r"^[mf]?$", title="性别")
    mb_sex: str = Body(None, pattern=r"^[mf]?$", title="성별")
    mb_email: EmailStr = Body(..., title="电子邮件", description="请输入您的电子邮件格式.")
    mb_homepage: str = Body(None, title="主页")
    mb_zip: str = Body(None, title="邮政号码")
    mb_addr_jibeon: str = Body(None, title="地址")
    mb_addr1: str = Body(None, title="基本地址")
    mb_addr2: str = Body(None, title="地址的其余部分")
    mb_addr3: str = Body(None, title="其他地址")
    mb_tel: str = Body(None, title="电话号码")
    mb_hp: str = Body(None, title="移动电话号码")
    mb_signature: str = Body(None, title="签名")
    mb_profile: str = Body(None, title="自我介绍")

    mb_mailling: int = Body(None, title="不管你是否收到邮件")
    mb_sms: int = Body(None, title="SMS 是否接收")
    mb_open: int = Body(None, title="是否公开会员信息")

    mb_1: str
    mb_2: str
    mb_3: str
    mb_4: str
    mb_5: str
    mb_6: str
    mb_7: str
    mb_8: str
    mb_9: str
    mb_10: str

    @field_validator('mb_zip', mode='after')
    @classmethod
    def divide_zip(cls, v: str) -> str:
        """正面和背面的邮政号码，分别 3被一个地方分开"""
        cls.mb_zip1, cls.mb_zip2 = set_zip_code(v)
        return v

    @model_validator(mode='after')
    def check_passwords_match(self) -> 'UpdateMember':
        """检查密码和密码验证是否匹配"""
        pw1 = self.mb_password
        pw2 = self.mb_password_re

        if pw1 is not None:
            if pw1 != pw2:
                raise ValueError('密码不匹配.')
            self.mb_password = create_hash(pw1)
        else:
            del self.mb_password

        return self

    @model_validator(mode='after')
    def init_update_fields(self) -> 'UpdateMember':
        """UpdateMemberModel初始化一个未声明的字段"""
        self.mb_nick_date = datetime.now()
        self.mb_open_date = datetime.now()
        # 删除加入成员不需要的字段
        del self.mb_password_re
        del self.mb_zip

        return self


class RegisterResponse(MessageResponse):
    """成员连接处理响应模型"""
    mb_id: str
    mb_name: str
    mb_nick: str


class MemberResponse(BaseModel):
    """会员信息响应模型"""
    mb_id: str
    mb_nick: str
    mb_email: str
    mb_point: int
    mb_profile: str

    mb_icon_path: str
    mb_image_path: str

    mb_1: str
    mb_2: str
    mb_3: str
    mb_4: str
    mb_5: str
    mb_6: str
    mb_7: str
    mb_8: str
    mb_9: str
    mb_10: str

    @model_validator(mode='before')
    def init_fields(self) -> 'MemberResponse':
        """
        字段初始化
        - 成员图标/图像路径设置
        """
        self.mb_icon_path = ImageService.get_icon_path(self.mb_id)
        self.mb_image_path = ImageService.get_image_path(self.mb_id)
        return self


class MemberMeResponse(MemberResponse):
    """会员信息响应模型"""
    mb_name: str
    mb_memo_cnt: int
    mb_scrap_cnt: int


class SearchMemberId(BaseModel):
    """查找会员的Idias模型"""
    mb_name: str = Body(..., title="姓名", description="成员名称")
    mb_email: EmailStr = Body(..., title="电子邮件", description="会员电子邮件")


class SearchMemberIdResponse(BaseModel):
    """成员 ID 查找响应模型"""
    mb_id: str
    register_date: datetime

class SearchMemberPassword(BaseModel):
    """成员密码查找模型"""
    mb_id: str = Body(..., title="Idie")
    mb_email: EmailStr = Body(..., title="电子邮件")


class ResetMemberPassword(BaseModel):
    """会员密码重置模型"""
    password: str = Body(..., title="密码")
    password_confirm: str = Body(..., title="检查您的密码")

    @model_validator(mode='after')
    def check_passwords_match(self) -> 'ResetMemberPassword':
        """检查密码和密码验证是否匹配"""
        pw1 = self.password
        pw2 = self.password_confirm
        if pw1 != pw2:
            raise ValueError('密码不匹配.')

        self.password = create_hash(pw1)

        return self
